package com.yin.project.admin.util;

import com.yin.project.admin.rbac.model.LoginLogEntity;
import com.yin.project.admin.rbac.model.MenuEntity;
import org.apache.commons.lang3.StringUtils;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 根据提供的实体类生成Sql语句
 * <p>
 * Created by Eason on 2016/12/5.
 */
public class GenerateDdlUtil {

    /**
     * 1.处理表名
     * 2.处理字段名称
     * 3.字段类型
     * 4.字段长度
     * 5.是否为空
     *
     * @param clazz 实体类
     */
    public static String generateDdl(Class<?> clazz) {
        StringBuilder builder = new StringBuilder();
        //创建表名
        Table table = clazz.getAnnotation(Table.class);
        if (table != null) {
            String tableName = table.name();
            builder.append("CREATE TABLE `").append(tableName).append("`(\n");
        }
        //字段解析
        List<ColumeDef> columeDefs = resolveColumnAnnotations(clazz);
        for (ColumeDef columeDef : columeDefs) {
            builder.append(columeDef.toString()).append(",\n");
        }
        builder.append(")ENGINE=InnoDB DEFAULT CHARSET=utf8;");
        return builder.toString();
    }

    private static List<ColumeDef> resolveField(Class<?> clazz){
        List<ColumeDef> columeDefs = new ArrayList<ColumeDef>();
        List<Field> fields = getClassField(clazz);
        for (Field field : fields) {
            ColumeDef columeDef = new ColumeDef();
            String type = field.getType().getSimpleName();
            columeDef.setType(type);
            String fieldName = field.getName();
            columeDef.setFieldName(fieldName);
            columeDefs.add(columeDef);
        }
        return columeDefs;
    }

    private static List<ColumeDef> resolveColumnAnnotations(Class<?> clazz) {
        List<ColumeDef> columeDefs = new ArrayList<ColumeDef>();
        List<Field> fields = getClassField(clazz);
        for (Field field : fields) {
            ColumeDef columeDef = new ColumeDef();
            String type = field.getType().getSimpleName();
            columeDef.setType(type);
            Annotation[] annotations = field.getAnnotations();
            if (annotations.length < 1) {
                continue;
            }
            for (Annotation annotation : annotations) {
                if (annotation instanceof Column) {
                    String fieldName = ((Column) annotation).name();
                    if (StringUtils.isEmpty(fieldName)) {
                        fieldName = field.getName().toLowerCase();
                    }
                    columeDef.setFieldName(fieldName);
                }
                if (annotation instanceof Id) {

                }
                columeDefs.add(columeDef);
            }
        }
        return columeDefs;
    }

    /**
     * 获取类中的字段
     *
     * @param clazz
     * @return
     */
    private static List<Field> getClassField(Class<?> clazz) {
        List<Field> list = Collections.emptyList();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            list.add(field);
        }
        if (clazz.getSuperclass() != null) {
            list.addAll(getClassField(clazz.getSuperclass()));
        }
        return list;
    }

    public static void main(String[] args) {
        String ddl = GenerateDdlUtil.generateDdl(LoginLogEntity.class);
        System.out.println(ddl);
    }
}

/**
 * 列字段定义
 */
class ColumeDef {
    private String fieldName;
    private String type;

    public String getFieldName() {
        return fieldName;
    }

    protected void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    private String getMysqlType(String type) {
        if (StringUtils.equalsIgnoreCase(type, "Date")) {
            return "timestamp(6)";
        } else if (StringUtils.equalsIgnoreCase(type, "boolean")) {
            return "bigint(20)";
        } else if (StringUtils.equalsIgnoreCase(type, "int")) {
            return "tinyint(1)";
        } else {
            return "varchar(50)";
        }

    }

    @Override
    public String toString() {
        return fieldName + " " + getMysqlType(type);
    }
}
